/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com */

/*
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#include "particle_engine.h"

#include <stdio.h>
#include <iostream>
#include <map>

namespace tri {


TParticle::TParticle() : 
	tri::TGlyph(),
	m_Active(false),
	m_LifeSpan(1.0){
	
	m_Timer.setMode(TIMER_TYPE);
}

TParticle::~TParticle(){} 

void TParticle::display(){
	if (m_Active){
		tri::TGlyph::display();
	}
}

void TParticle::update(){
	TGlyph::update();
	
	if (isActive()){
		if (m_Timer.getProgress() == 1.0){
			setActive(false);
			return;
		}
		
		TVector pos = getPosition();
		
		float new_elapsedTime  = m_Timer.getElapsedTime();
		float time_diff = new_elapsedTime - elapsedTime;
		
		m_Velocity+=m_Gravity*time_diff;
		pos+= m_Velocity*time_diff;
		
		setPosition(pos);
	}
	
}

void TParticle::setActive(bool b){
	m_Active = b;
	if (b){
		m_Timer.setDurationTime(m_LifeSpan);
		m_Timer.reset();
		m_Timer.start();
		elapsedTime = 0;
	}
}

bool TParticle::isActive(){
	return m_Active;
}

void TParticle::setLifeSpan(float l){
	m_LifeSpan = l;
}

void TParticle::setVelocity(TVector vel){
	m_Velocity = vel;
}

void TParticle::setGravity(TVector grav){
	m_Gravity = grav;
}
	

TParticleEngine::TParticleEngine() : tri::TEntity() , m_PoolSize(0){
	m_MinLifeSpan = 0;
	m_MaxLifeSpan = 0;
	m_ParticleSize = 1;
}

TParticleEngine::~TParticleEngine(){};

void TParticleEngine::display(){
	for(unsigned int i=0; i<m_Pool.size() ;i++){
		m_Pool[i].render();
	}
}


void TParticleEngine::reset(){
	
	if (m_Pool.size() != m_PoolSize){
		m_Pool.clear();
		for(unsigned int i=0; i<m_PoolSize ;i++){
			m_Pool.push_back(TParticle());
		}
		
		for(unsigned int i=0; i<m_Pool.size() ;i++){
			if(!m_Pool[i].isActive()){
				resetParticle(&m_Pool[i]);
			}
		}
	}
}

void TParticleEngine::setParticleCount(unsigned int size){
	m_PoolSize = size;
	reset();
}

void TParticleEngine::update(){
	for(unsigned int i=0; i<m_Pool.size() ;i++){
		m_Pool[i].update();
		
		if(!m_Pool[i].isActive()){
			resetParticle(&m_Pool[i]);
		}
	}
}

void TParticleEngine::setParticleVelocity(TVector v){
	setParticleVelocity(v,v);
}

void TParticleEngine::setParticleVelocity(TVector min,TVector max){
	m_MinVelocity = min;
	m_MaxVelocity = max;
}

void TParticleEngine::setParticleGravity(TVector g){
	m_Gravity = g;
}

void TParticleEngine::setParticleColor(graphics::TColor c){
	setParticleColor(c,c);
}

void TParticleEngine::setParticleColor(graphics::TColor s, graphics::TColor e){
	m_StartColor = s;
	m_EndColor = e;
}

void TParticleEngine::setParticlePosition(TVector p){
	setParticlePosition(p,p);
}

void TParticleEngine::setParticlePosition(TVector min, TVector max){
	m_MinOrigPosition = min;
	m_MaxOrigPosition = max;
}

void TParticleEngine::setParticleLifeSpan(float ls){
	setParticleLifeSpan(ls,ls);
}

void TParticleEngine::setParticleLifeSpan(float min, float max){
	m_MinLifeSpan = min;
	m_MaxLifeSpan = max;
}

void TParticleEngine::setParticleImage(std::string image){
	mParticleImage = image;
}

void TParticleEngine::setParticleSize(float s){
	m_ParticleSize = s;
}

void TParticleEngine::resetParticle(TParticle* p){
	p->setPosition(tri::utils::randomVector(m_MinOrigPosition,m_MaxOrigPosition));
	float ls = tri::utils::randomFloat(m_MinLifeSpan,m_MaxLifeSpan);
	p->setLifeSpan( ls );
	
	p->setColor(m_StartColor.asRGBA());
	p->setTargetColor(m_EndColor.asRGBA(),ls);
	
	p->setVelocity(tri::utils::randomVector(m_MinVelocity,m_MaxVelocity));
	p->setSize(m_ParticleSize,m_ParticleSize,0);
	p->setActive(true);
	p->setImage(mParticleImage);
	p->setGravity(m_Gravity);
}


}
